#include "ZlgCan.h"
#include <cstring>
#include "utility.h"

namespace ZlgCan {


//设置自定义波特率, 需要从CANMaster目录下的baudcal生成字符串
bool ZlgCan::SetCustomBaudrate()
{

	// char path[50] = {0};
	// char value[100] = {0};
	// string baudrate = Utility::W2AEx(custom_baudrate_);
	// sprintf_s(path, "%d/baud_rate_custom", channel_index_);
	// sprintf_s(value, "%s", baudrate.data());
	// return 1 == ZCAN_SetValue(device_handle_, path, value);
	return 1;
}

//设置USBCANFD卡波特率
bool ZlgCan::SetCanfdBaudrate()
{

	char path[50] = { 0 };
	sprintf_s(path, "%d/canfd_abit_baud_rate", channel_index_);
	char value[10] = { 0 };
	sprintf_s(value, "%d", 500000);
	int ret_a = ZCAN_SetValue(device_handle_, path, value);

	sprintf_s(path, "%d/canfd_dbit_baud_rate", channel_index_);
	sprintf_s(value, "%d", 2000000);
	int ret_d = ZCAN_SetValue(device_handle_, path, value);
	return 1 == (ret_a&&ret_d);
}

//设置终端电阻使能
bool ZlgCan::SetResistanceEnable()
{

	char path[50] = {0};
	sprintf_s(path, "%d/initenal_resistance", channel_index_);
	char value[10] = {0};
	sprintf_s(value, "%d", resistance_enable_);
	return 1 == ZCAN_SetValue(device_handle_, path, value);
}

	ZlgErrorCode ZlgCan::ZlgCan::Open()
	{
		device_handle_ = ZCAN_OpenDevice(ZCAN_USBCANFD_200U, device_index_, 0);
    	if (INVALID_DEVICE_HANDLE == device_handle_)
    	{
    		std::cout << "open usbcan device failed!" << std::endl;
    		return ZlgErrorCode::ERROR_OPEN_DEVICE_FAILED;
    	}
    	device_opened_ = TRUE;

		ZCAN_CHANNEL_INIT_CONFIG config;
		memset(&config, 0, sizeof(config));

        char path[50] = {0};
        char value[100] = {0};
        sprintf_s(path, "%d/canfd_standard", channel_index_);
        sprintf_s(value, "%d", 0);
        ZCAN_SetValue(device_handle_, path, value);


		// if (!SetCustomBaudrate())
		// {
		// 	std::cout << "设置自定义波特率失败!" << std::endl;
		// 	return ZlgErrorCode::ERROR_OPEN_DEVICE_FAILED;
		// } else {
		// 	std::cout << "设置自定义波特率成功!" << std::endl;
		// }


		if (!SetCanfdBaudrate())
		{
			std::cout << "set can baudrate failed!" << std::endl;
			return ZlgErrorCode::ERROR_SET_BAUDRATE_FAILED;
		}

        config.can_type = TYPE_CANFD;
        config.canfd.mode = work_mode_index_;
        config.canfd.filter = filter_mode_;
        config.canfd.acc_code = 0x00000000;
        config.canfd.acc_mask = 0xffffffff;

    	channel_handle_ = ZCAN_InitCAN(device_handle_, channel_index_, &config);
    	if (INVALID_CHANNEL_HANDLE == channel_handle_)
    	{
    		std::cout << "init can device failed!" << std::endl;
    		return ZlgErrorCode::ERROR_SET_INIT_PARA_FAILED;
    	}

        if (resistance_enable_ && !SetResistanceEnable())
        {
    		std::cout << "set can resistance failed!" << std::endl;
    		return ZlgErrorCode::ERROR_SET_INIT_PARA_FAILED;
        }

    	if (ZCAN_StartCAN(channel_handle_) != STATUS_OK)
    	{
    		std::cout << "start can device failed!" << std::endl;
    		return ZlgErrorCode::ERROR_START_DEVICE_FAILED;
    	}

    	//std::cout << "start usbcanfd-200u succeed" << std::endl;
		return ZlgErrorCode::SUCCEED;
	}

	ZlgErrorCode ZlgCan::Reset()
	{

		return ZlgErrorCode::SUCCEED;
	}

	ZlgErrorCode ZlgCan::Send(uint32_t canId, std::string data, int delaymilliseconds, int repeatCount, int frameType)
	{
		if (data.empty())
			return ZlgErrorCode::ERROR_INVALUTE_DATE;
		int  canfd_exp_index_ = 1;
        int  send_type_index_ = 0;
        int  add_delay_flag = 1;
    	UINT result;//发送的帧数

    	std::cout << "send canframe id:0x" << hex << canId << " data:0x " << data << std::endl;

    	if (0 == frameType)//can
    	{
     	    ZCAN_Transmit_Data can_data;
     	    memset(&can_data, 0, sizeof(can_data));
     	    can_data.frame.can_id = MAKE_CAN_ID(canId, frameType, 0, 0);
     	    can_data.frame.can_dlc = Utility::split(can_data.frame.data, CAN_MAX_DLEN, data, ' ', 16);
     	    can_data.transmit_type = send_type_index_;

            if (repeatCount > 0)
            {
                ZCAN_Transmit_Data* pData = new ZCAN_Transmit_Data[repeatCount];
                for (int i=0; i<repeatCount; ++i)
                {
                    memcpy_s(&pData[i], sizeof(ZCAN_Transmit_Data), &can_data, sizeof(can_data));
                }

                result = ZCAN_Transmit(channel_handle_, pData, repeatCount);
                delete [] pData;
            }
    	}
    	else //canfd
    	{
    		ZCAN_TransmitFD_Data canfd_data;
		    memset(&canfd_data, 0, sizeof(canfd_data));
		    canfd_data.frame.can_id = MAKE_CAN_ID(canId, frameType, 0, 0);
		    canfd_data.frame.len = Utility::split(canfd_data.frame.data, CANFD_MAX_DLEN, data, ' ', 16);
		    canfd_data.transmit_type = send_type_index_;
		    canfd_data.frame.flags |= canfd_exp_index_ ? CANFD_BRS : 0;

            if (repeatCount > 0)
            {
                ZCAN_TransmitFD_Data* pData = new ZCAN_TransmitFD_Data[repeatCount];
                for (int i=0; i<repeatCount; ++i)
                {
                    memcpy_s(&pData[i], sizeof(ZCAN_TransmitFD_Data), &canfd_data, sizeof(canfd_data));
                }

                result = ZCAN_TransmitFD(channel_handle_, pData, repeatCount);
                delete [] pData;
            }
    	}

    	if (result != repeatCount)
    	{
    		std::cout << "send canframe failed!" << std::endl;
    	}
    	else
    	{
    		std::cout << "send canframe succeed" << std::endl;
    	}
		return ZlgErrorCode::SUCCEED;
	}
	ZlgErrorCode ZlgCan::Receive(uint32_t& canId, std::vector<char>& data, int timeOut)
	{

		return ZlgErrorCode::SUCCEED;
	}
	ZlgErrorCode ZlgCan::ReadErrInfo()
	{
		return ZlgErrorCode();
	}
	ZlgErrorCode ZlgCan::Close()
	{
		ZCAN_ResetCAN(channel_handle_);
	    ZCAN_CloseDevice(device_handle_);
		device_opened_ = FALSE;
		//std::cout << "close can device succeed" << std::endl;
		return ZlgErrorCode::SUCCEED;
	}
}